package appapi.service.impl;

import appapi.Global.BusinessException;
import appapi.Request.ModulelistReq;
import appapi.Request.RolepermissionReq;
import appapi.Vo.AppVo.AppLoginVo;
import appapi.dao.*;
import appapi.entity.auth.*;
import appapi.service.ILoginService;
import appapi.utils.JwtUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class LoginService implements ILoginService {

    @Resource
    private StaffMapper staffMapper;
    @Resource
    private StaffroleMapper staffroleMapper;
    @Resource
    RolepermissionMapper rolepermissionMapper;
    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;
    @Resource
    OperatorMapper operatorMapper;
    @Autowired
    ModulelistMapper modulelistMapper;
    @Resource
    OrganizationImpl organization;

    /**
     * 用户登录
     *
     * @param account  电话
     * @param password 密码
     * @return
     */
    @Override
    public Map<String, Object> CheckLogin(String account, String password) {

        //用电话号码查询是否存在账号
        Map<String, Object> staffDto = staffMapper.selectAccount(account);
        //如果没找到账号则返回
        if (staffDto == null) {
            throw new BusinessException(500, "账号不存在");
        }
        //密码对比
        boolean matches = bCryptPasswordEncoder.matches(password, staffDto.get("staffPwd").toString());
        if (!matches)
            throw new BusinessException(501, "登录失败,账号或密码错误");

        //账号是否异常
        if ((Integer) staffDto.get("staffStatus") != 0)
            throw new BusinessException(501, "登录失败,账号状态异常!");

        JSONObject jsonObject = new JSONObject();
        jsonObject.putAll(staffDto);
        StaffEntity person = jsonObject.toBean(StaffEntity.class);

        //查到账号所拥有的权限
        List<Map<String, Object>> staffRole = staffroleMapper.selectByStaffId((Long) staffDto.get("staffId"));

        //把模块去重合并到一起
        Set<ModulelistEntity> roles = new HashSet<>();
        staffRole.forEach((role) -> {
            RolepermissionReq req = new RolepermissionReq();
            req.setRoleId((Long) role.get("roleId"));
            //查到权限所拥有的模块
            List<ModulelistEntity> roleModule = rolepermissionMapper.selectMoudleList(req);
            roles.addAll(roleModule);
        });


        //构建角色功能菜单
        List<ModuletypeModel> dtoList = new ArrayList<>();
        List<ModulelistEntity> menuList = roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId() == 0)
                .collect(Collectors.toList());
        //获取父级模块
        List<Long> father=roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId() != 0 )
                .map(ModulelistEntity::getParentId).collect(Collectors.toList());
        ModulelistReq childReq =new ModulelistReq();
        List<ModulelistEntity> allModule = modulelistMapper.list(childReq);
        List<ModulelistEntity>  fatherList = allModule.stream().filter(ModulelistEntity->father.contains(ModulelistEntity.getModuId()))
                .collect(Collectors.toList());
        menuList.addAll(fatherList);
        for (ModulelistEntity type : menuList
        ) {
            ModuletypeModel dto = new ModuletypeModel();
            dto.setModuId(type.getModuId());
            dto.setModuIcon(type.getModuIcon());
            dto.setModuSort(type.getModuSort());
            dto.setModuNote(type.getModuNote());
            dto.setModuType(type.getModuType());
            dto.setModuName(type.getModuName());
            dto.setModuState(type.getModuState());
            dto.setModuUrl(type.getModuUrl());
            dto.setModuTag(type.getModuTag());
            dto.setParentId(type.getParentId());
            dto.setParentName(type.getParentName());
            List<ModulelistEntity> child = roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId().equals(type.getModuId()))
                    .collect(Collectors.toList());
            dto.setChildren(child);
            dtoList.add(dto);
        }

        //加入该人员组织机构树
        //List<Map<String, Object>> orgaTree = organization.SelectOrgTree((Long) staffDto.get("orgaId"));
        //staffDto.put("orgaTree",orgaTree);

        //去除密码显示
        staffDto.remove("staffPwd");

        staffDto.put("staffRole", dtoList);

        //String token = tokenService.getToken(person);
        String jwtToken = JwtUtil.getJwtToken(Long.valueOf(staffDto.get("staffId").toString()),staffDto.get("staffMobile").toString(), staffDto.get("staffName").toString());
        staffDto.put("token", jwtToken);
        return staffDto;
    }

    /**
     * 获取token
     *
     * @param account  电话
     * @param password 密码
     * @return
     */
    @Override
    public String getToken(String account, String password) {

        //用电话号码查询是否存在账号
        Map<String, Object> staffDto = staffMapper.selectAccount(account);


        //如果没找到账号则返回
        if (staffDto == null) {
            throw new BusinessException(500, "账号不存在");
        }
        //密码对比
        boolean matches = bCryptPasswordEncoder.matches(password, staffDto.get("staffPwd").toString());
        if (!matches)
            throw new BusinessException(501, "登录失败,账号或密码错误");

        //账号是否异常
        if ((Integer) staffDto.get("staffStatus") != 0)
            throw new BusinessException(501, "登录失败,账号状态异常!");

        JSONObject jsonObject = new JSONObject();
        jsonObject.putAll(staffDto);
        StaffEntity person = jsonObject.toBean(StaffEntity.class);

        //查到账号所拥有的权限
        List<Map<String, Object>> staffRole = staffroleMapper.selectByStaffId((Long) staffDto.get("staffId"));

        //把模块去重合并到一起
        Set<ModulelistEntity> roles = new HashSet<>();
        staffRole.forEach((role) -> {
            RolepermissionReq req = new RolepermissionReq();
            req.setRoleId((Long) role.get("roleId"));
            //查到权限所拥有的模块
            List<ModulelistEntity> roleModule = rolepermissionMapper.selectMoudleList(req);
            roles.addAll(roleModule);
        });


        //构建角色功能菜单
        List<ModuletypeModel> dtoList = new ArrayList<>();
        List<ModulelistEntity> menuList = roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId() == 0)
                .collect(Collectors.toList());
        //获取父级模块
        List<Long> father=roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId() != 0 )
                .map(ModulelistEntity::getParentId).collect(Collectors.toList());
        ModulelistReq childReq =new ModulelistReq();
        List<ModulelistEntity> allModule = modulelistMapper.list(childReq);
        List<ModulelistEntity>  fatherList = allModule.stream().filter(ModulelistEntity->father.contains(ModulelistEntity.getModuId()))
                .collect(Collectors.toList());
        menuList.addAll(fatherList);
        for (ModulelistEntity type : menuList
        ) {
            ModuletypeModel dto = new ModuletypeModel();
            dto.setModuId(type.getModuId());
            dto.setModuIcon(type.getModuIcon());
            dto.setModuSort(type.getModuSort());
            dto.setModuNote(type.getModuNote());
            dto.setModuType(type.getModuType());
            dto.setModuName(type.getModuName());
            dto.setModuState(type.getModuState());
            dto.setModuUrl(type.getModuUrl());
            dto.setModuTag(type.getModuTag());
            dto.setParentId(type.getParentId());
            dto.setParentName(type.getParentName());
            List<ModulelistEntity> child = roles.stream().filter(ModulelistEntity -> ModulelistEntity.getParentId().equals(type.getModuId()))
                    .collect(Collectors.toList());
            dto.setChildren(child);
            dtoList.add(dto);
        }

        //加入该人员组织机构树
        //List<Map<String, Object>> orgaTree = organization.SelectOrgTree((Long) staffDto.get("orgaId"));
        //staffDto.put("orgaTree",orgaTree);

        //去除密码显示
        //staffDto.remove("staffPwd");

        //staffDto.put("staffRole", dtoList);

        //String token = tokenService.getToken(person);
        String jwtToken = JwtUtil.getJwtToken(Long.valueOf(staffDto.get("staffId").toString()),staffDto.get("staffMobile").toString(), staffDto.get("staffName").toString());
        staffDto.clear();
        staffDto.put("token", jwtToken);

        return jwtToken;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AppLoginVo> AppUserLogin(String mobile, String wxId) {
        List<AppLoginVo> vos = new ArrayList<>();
        //如果电话不为空,则未绑定微信id,第一次登录小程序
        if (StringUtils.isNotBlank(mobile)) {
            Map<String, Object> staff = staffMapper.selectMobile(mobile);
            //如果管理人员没查到该电话,则查操作人员
            Map<String, Object> opera = operatorMapper.selectAllByWxIdAndOperMobile(null, mobile);
            if (staff == null) {
                //没查到操作人员退出
                if (opera == null) {
                    throw new BusinessException(500, "未找到该人员!");
                }
                //查到则再查一次微信id,看看是否绑定过
                if (operatorMapper.selectAllByWxIdAndOperMobile(null, mobile) == null) {
                    throw new BusinessException(500, "该账号已被绑定,请联系后台管理人员!");
                }
                //否则登录成功
                AppLoginVo vo = setOperUserInfo(opera);
                vos.add(vo);
                if (operatorMapper.updateByOperWxid(wxId, vo.getUserPhone()) == 0) {
                    throw new BusinessException(500, "登录失败!");
                }
            }
            //查到则再查一次管理人员,再查微信id,看看是否绑定过
            else {
                //如果不为空,则将权限加入进去
                if (opera != null) {
                    AppLoginVo vo = setOperUserInfo(opera);
                    vos.add(vo);
                    //查到则再查一次微信id,看看是否绑定过
                    if (operatorMapper.selectAllByWxIdAndOperMobile(null, mobile) == null) {
                        throw new BusinessException(500, "该账号已被绑定,请联系后台管理人员!");
                    }
                    if (operatorMapper.updateByOperWxid(wxId, vo.getUserPhone()) == 0) {
                        throw new BusinessException(500, "登录失败!");
                    }
                }

                if (staffMapper.selectAllByStaffMobile(mobile) == null) {
                    throw new BusinessException(500, "该账号已被绑定,请联系后台管理人员!");
                }
                AppLoginVo vo = setStaffUserInfo(staff);
                vos.add(vo);
                if (staffMapper.updateByStaffWxid(wxId, vo.getUserPhone()) == 0) {
                    throw new BusinessException(500, "登录失败!");
                }
            }
        }
        //电话为空则为小程序直接登录
        else {
            Map<String, Object> staffWx = staffMapper.selectWxid(wxId);
            Map<String, Object> operWx = operatorMapper.selectAllByWxIdAndOperMobile(wxId, "");
            //没查到管理人员则查操作人员
            if (staffWx == null) {
                //如果都为空则退出
                if (operWx == null) {
                    throw new BusinessException(500, "第一次登录,请授权手机号进入!");
                }
                //否则返回信息
                vos.add(setOperUserInfo(operWx));
            } else {
                //如果一样拥有操作人员账号,则加入返回权限中
                if (operWx != null) {
                    vos.add(setOperUserInfo(operWx));
                }
                vos.add(setStaffUserInfo(staffWx));
            }
        }
        return vos;
    }

    private AppLoginVo setStaffUserInfo(Map<String, Object> staffWx) {
        AppLoginVo vo = new AppLoginVo();
        vo.setUserId((Long) staffWx.get("staffId"));
        vo.setUserName(staffWx.get("staffName").toString());
        vo.setUserType(0);
        vo.setUserSex((Integer) staffWx.get("staffSex"));
        vo.setUserPic((String) staffWx.getOrDefault("staffPic", ""));
        vo.setUserPhone(staffWx.get("staffMobile").toString());
        vo.setUserOrgaId((Long) staffWx.get("orgaId"));
        vo.setUserOrga((String) staffWx.getOrDefault("orgeName", ""));
        vo.setUserOrgaPath(staffWx.get("orgaPathIds").toString());
        vo.setToken(JwtUtil.getJwtToken(vo.getUserId(),vo.getUserPhone(), vo.getUserName()));
        return vo;
    }

    private AppLoginVo setOperUserInfo(Map<String, Object> operWx) {
        AppLoginVo vo = new AppLoginVo();
        vo.setUserId((Long) operWx.get("operId"));
        vo.setUserName(operWx.get("operName").toString());
        vo.setUserType((Integer) operWx.get("operType") == 0 ? 1 : 2);
        vo.setUserSex((Integer) operWx.get("operSex"));
        vo.setUserPic((String) operWx.getOrDefault("operHeadpic", ""));
        vo.setUserPhone(operWx.get("operMobile").toString());
        vo.setUserOrgaPath(operWx.get("orgaPathIds").toString());
        vo.setToken(JwtUtil.getJwtToken(vo.getUserId(),vo.getUserPhone(), vo.getUserName()));
        return vo;
    }
}
